import time
import datetime

from flask import render_template, request, current_app, jsonify, redirect, session, url_for, g, Response, make_response
from sqlalchemy import or_

from . import admin_blur
from flask.views import MethodView

# 创建api
from ... import constants, db
from ...models import User, News, Category
from ...utils.common import login_require
from ...utils.image_storage import image_storage
from ...utils.response_code import RET

"""
新闻分类添加/修改
请求路径: /admin/add_category
请求方式: POST
请求参数: id,name
返回值:errno,errmsg
"""


@admin_blur.route('/add_category', methods=['POST'])
def add_category():
    # 获取参数
    category_id = request.json.get('id')
    category_name = request.json.get('name')
    # 校验参数 为空校验
    if not category_name:
        return jsonify(errno=RET.PARAMERR ,errmsg="分类不能为空")
    if not category_name:
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
    # 根据是否携带id 来确定是增加还是修改 修改没有id
    if category_id:
        try:
            category = Category.query.get(category_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="数据库异常，查取分类失败")
        # 修改分类名
        if not category:
            return jsonify(errno=RET.DATAERR ,errmsg="分类不存在")
        category.name = category_name
        return jsonify(errno=RET.OK, errmsg="修改新闻分类成功")
    # 没有id 说明是新增分类
    category = Category()
    category.name = category_name
    try:
        db.session.add(category)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库异常，添加分类失败")
    return jsonify(errno=RET.OK, errmsg="添加新分类成功")


"""
新闻分类管理
请求路径: /admin/news_category
请求方式: GET
请求参数: GET,无
返回值:GET,渲染news_type.html页面, data数据
"""


@admin_blur.route('/news_category')
def news_category():
    try:
        category_list = Category.query.all()
    except Exception as e:
        current_app.logger.error(e)
        return render_template('admin/news_type.html', errmsg="数据库异常，查取新闻种类失败")
    data = {
        "category_list": [category.to_dict() if category else None for category in category_list]
    }
    return render_template('admin/news_type.html', data=data)


"""
请求路径: /admin/news_edit_detail
请求方式: GET, POST
请求参数: GET, news_id, POST(news_id,title,digest,content,index_image,category_id)
返回值:GET,渲染news_edit_detail.html页面,data字典数据, POST(errno,errmsg)
"""


@admin_blur.route('/news_edit_detail', methods=['GET', 'POST'])
def news_edit_detail():
    if request.method == 'GET':
        # 获取参数
        news_id = request.args.get('news_id', '')
        # 获取新闻对象
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            return render_template('admin/news_edit_detail.html', errmsg='数据库异常，获取新闻失败')
        if not news:
            return render_template('admin/news_edit_detail.html', errmsg='该新闻不存在')
        # 查询数据库的所有分类
        try:
            category_list = Category.query.all()
        except Exception as e:
            current_app.logger.error(e)
            return render_template('admin/news_edit_detail.html', errmsg='查询分类失败')

        data = {
            'news': news.to_dict(),
            'categorys': [category.to_dict() if category else None for category in category_list]
        }
        return render_template('admin/news_edit_detail.html', data=data)
    # post请求获取参数
    news_id = request.form.get('news_id')
    title = request.form.get('title')
    digest = request.form.get('digest')
    content = request.form.get('content')
    index_image = request.files.get('index_image')
    category_id = request.form.get('category_id')
    # 非空校验
    if not all([news_id, title, digest, content, category_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
    # 查询新闻
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库异常，查询新闻失败")
    if not news:
        return jsonify(errno=RET.DATAERR, errmsg="该新闻不存在")
    # 上传图片
    # 首先要判断是否有新图片上传了
    # 修改新闻属性
    news.title = title
    news.digest = digest
    news.content = content
    if index_image:
        try:
            image_name = image_storage(index_image.read())
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="七牛云务器异常")

        if not image_name:
            return jsonify(errno=RET.NODATA, errmsg="上传图片错误")

        news.index_image_url = constants.QINIU_DOMIN_PREFIX + image_name
    # 返回响应
    return jsonify(errno=RET.OK, errmsg="新闻板式编辑成功")


"""
请求路径: /admin/news_edit
请求方式: GET
请求参数: GET, p, keywords

"""


@admin_blur.route('/news_edit')
def news_edit():
    # 获取参数
    page = request.args.get('p', 1)
    keywords = request.args.get('keywords', '')
    # 转换参数
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
    # 分页查询所有的新闻
    try:
        filters = []
        if keywords:
            filters.append(News.title.contains(keywords))
        paginate = News.query.filter(*filters).order_by(
            News.create_time.desc()).paginate(page, 10, False)
    except Exception as e:
        current_app.logger.error(e)
        return render_template('admin/news_edit.html', errmsg='获取未审核新闻失败')
    # 拼接参数
    totalpage = paginate.pages
    currentpage = paginate.page
    items = paginate.items
    # 渲染页面
    data = {
        'totalpage': totalpage,
        "currentpage": currentpage,
        'news_list': [news.to_review_dict() if news else None for news in items]
    }
    return render_template('admin/news_edit.html', data=data)


"""
新闻详情页展示
请求路径: /admin/news_review_detail
请求方式: GET,POST
请求参数: GET, news_id, POST,news_id, action
返回值:GET,渲染news_review_detail.html页面,data字典数据
"""


@admin_blur.route('/news_review_detail', methods=['GET', 'POST'])
def news_review_detail():
    if request.method == 'GET':
        # 获取参数
        news_id = request.args.get('news_id', '')
        # 获取新闻对象
        try:
            news = News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            return render_template('admin/news_review_detail.html', errmsg='数据库异常，获取新闻失败')
        if not news:
            return render_template('admin/news_review_detail.html', errmsg='该新闻不存在')
        data = {
            'news': news.to_dict()
        }
        return render_template('admin/news_review_detail.html', data=data)
    # post请求获取参数
    action = request.json.get('action')
    news_id = request.json.get('news_id')
    # 非空校验
    if not all([action, news_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
    # 动作校验
    if action not in ('accept', 'reject'):
        return jsonify(errno=RET.PARAMERR, errmsg="参数错误")
    # 查询新闻
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库异常，查询新闻失败")
    if not news:
        return jsonify(errno=RET.DATAERR, errmsg="该新闻不存在")
    # 根据操作类型修改新闻状态
    if action == 'accept':
        news.status = 0
    else:
        news.status = -1
        reason = request.json.get('reason', '')
        if not reason:
            return jsonify(errno=RET.PARAMERR, errmsg="请填写拒绝原因")
        news.reason = reason
    # 返回响应
    return jsonify(errno=RET.OK, errmsg="审核成功")


"""
请求路径: /admin/news_review
请求方式: GET
请求参数: GET, p,keyword
返回值:渲染user_list.html页面,data字典数据
"""


@admin_blur.route('/news_review')
def news_review():
    # 获取参数
    page = request.args.get('p', 1)
    keywords = request.args.get('keywords', "")
    # 转换参数
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1
    # 分页查询 查询未通过和 不通过的新闻 status== 1，-1
    try:
        filters = [or_(News.status == 1, News.status == -1)]
        if keywords:
            filters.append(News.title.contains(keywords))
        paginate = News.query.filter(*filters).order_by(
            News.create_time.desc()).paginate(page, 10, False)
    except Exception as e:
        current_app.logger.error(e)
        return render_template('admin/news_review.html', errmsg='获取未审核新闻失败')
    # 拼接参数
    totalpage = paginate.pages
    currentpage = paginate.page
    items = paginate.items
    # 渲染页面
    data = {
        'totalpage': totalpage,
        "currentpage": currentpage,
        'news_list': [news.to_review_dict() if news else None for news in items]
    }
    return render_template('admin/news_review.html', data=data)


"""
请求路径: /admin/user_list
请求方式: GET
请求参数: p
返回值:渲染user_list.html页面,data字典数据
返回值解释:
"""


@admin_blur.route('/user_list')
def user_list():
    # 获取参数
    page = request.args.get('p', 1)
    # 参数转换
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1

    # 查询用户获取paginate对象
    paginate = User.query.filter(User.is_admin == False).paginate(page, 20, False)
    # 解析数据
    totalpage = paginate.pages
    currentpage = paginate.page
    items = paginate.items
    data = {
        'totalpage': totalpage,
        'currentpage': currentpage,
        'user_list': [user.to_admin_dict() if user else None for user in items]
    }
    return render_template('admin/user_list.html', data=data)


"""
请求路径: /admin/user_count
请求方式: GET
请求参数: 无
返回值:渲染页面user_count.html,字典数据
"""


@admin_blur.route('/user_count')
def user_count():
    # 1.获取用户总数
    try:
        total_count = User.query.filter(User.is_admin == False).count()
    except Exception as e:
        current_app.logger.error(e)
        return render_template('admin/user_count.html', errmsg='获取用户总人数失败', data={})
    # 2.获取月活人数
    localtime = time.localtime()
    month_start_str = '%s-%s-01' % (localtime.tm_year, localtime.tm_mon)
    month_start_datetime = datetime.datetime.strptime(month_start_str, '%Y-%m-%d')
    try:
        month_count = User.query.filter(User.is_admin == False, User.last_login >= month_start_datetime).count()
    except Exception as e:
        current_app.logger.error(e)
        return render_template('admin/user_count.html', errmsg='获取月活跃量信息失败')
    # 3.获取日活人数
    day_start_str = '%s-%s-%s' % (localtime.tm_year, localtime.tm_mon, localtime.tm_mday)
    day_start_datetime = datetime.datetime.strptime(day_start_str, '%Y-%m-%d')
    try:
        day_count = User.query.filter(User.is_admin == False, User.last_login >= day_start_datetime).count()
    except Exception as e:
        current_app.logger.error(e)
        return render_template('admin/user_count.html', errmsg='获取日活跃量信息失败', data={})
    # 4.获取对应时间段内的活动人数
    active_date = []
    active_count = []
    for i in range(31):
        # 当天开始的时间
        began_time = day_start_datetime - datetime.timedelta(days=i)
        # 当天开始的后一天
        end_time = day_start_datetime - datetime.timedelta(days=i - 1)
        # 查询这一时期的活跃用户人数
        try:
            everyday_active_count = User.query.filter(User.is_admin == False, User.last_login >= began_time,
                                                      User.last_login <= end_time).count()

            active_date.append(began_time.strftime("%Y-%m-%d"))
            active_count.append(everyday_active_count)
        except Exception as e:
            current_app.logger.error(e)
            return render_template('admin/index.html', data={})
    # 5.携带数据
    data = {
        'total_count': total_count,
        'month_count': month_count,
        'day_count': day_count,
        "active_data": active_date[::-1],
        "active_count": active_count
    }
    return render_template('admin/user_count.html', data=data)


"""
请求路径: /admin/login
请求方式: GET, POST
请求参数: GET, 无, POST, username, password
"""


class AdminLogin(MethodView):
    def get(self):
        # 如果已经登录
        if session.get('is_admin'):
            return redirect('/admin/index')
        return render_template('admin/login.html')

    def post(self):
        # 获取参数

        username = request.form.get('username')
        password = request.form.get('password')
        # 非空校验
        if not all([username, password]):
            return render_template('admin/login.html', errmsg="参数不全")
        try:
            user = User.query.filter(User.nick_name == username, User.is_admin == True).first()
        except Exception as e:
            current_app.logger.error(e)
            return render_template('admin/login.html', errmsg='查取用户失败')
        if not user:
            return render_template('admin/login.html', errmsg="管理员不存在")
        if not user.check_passowrd(password):
            return render_template('admin/login.html', errmsg='密码错误')
        # 保存session
        session['user_id'] = user.id
        session['is_admin'] = True  # 管理员标识
        # 返回响应
        return redirect(url_for('admin.admin_index'))


admin_blur.add_url_rule('/login', view_func=AdminLogin.as_view('login'))

# 后台主页显示
"""
请求路径: /admin/index
请求方式: GET
请求参数: 无
返回值:渲染页面index.html,user字典数据
"""


@admin_blur.route('/index')
@login_require
def admin_index():
    data = {
        'user_info': g.user.to_dict() if g.user else None
    }
    return render_template('admin/index.html', data=data)


"""
请求钩子
拦截访问admin的请求，只有管理员才能访问
"""


@admin_blur.before_request
def before_request():
    """if request.url.endswith('/admin/login'):
        pass
    else:
        if session.get('is_admin'):
            pass
        else:
            return redirect('/')"""
    # 改进
    if not request.url.endswith('admin/login'):
        if not session.get('is_admin'):
            return redirect('/')
